#pragma once
#include "Log.hpp"
#include <iostream>
#include <unistd.h>
#include <memory>
#include <vector>
#include <queue>
#include <functional>
#include <condition_variable>
#include <mutex>
#include <string>
#include <thread>
namespace MyThreadPool
{

    // using namespace LogModule;

    using thread_t = std::shared_ptr<std::thread>;

    int defaultnum = 5;
    template <class T>
    class threadpool
    {
    private:
        void defaultfun()
        {
            while (true)
            {
                std::cout << "这是一个测试函数";
                sleep(1);
            }
        }
        bool IsEmpty() { return _taskq.empty(); }
        void HandlerTask(std::string name)
        {
            // 1. 拿任务
            while (true)
            {
                T t;
                {
                    std::unique_lock<std::mutex> _lk(_mtx);
                    // _lk.lock();
                    // 如果没有任务的话只能去阻塞住
                    std::cout << "线程： " << name << ", 进入HandlerTask"; 
                    while (IsEmpty() && _isruning)
                    {
                        std::cout << "开始等待" << std::endl;
                        _wait_num++;
                        _cond.wait(_lk); //这个等待完之后还会去加锁吗? 
                        std::cout << "唤醒线程" << std::endl;
                        _wait_num--;
                    }
                    if (IsEmpty() && !_isruning) break;
                    t = _taskq.front();
                    _taskq.pop();
                    _lk.unlock();
                }
                // 2. 处理任务
                t();
            }
        }

        threadpool(int num = defaultnum) : _num(num) , _wait_num(0),_isruning(false)
        {
            _isruning = true;
            for (int i = 0; i < num; i++)
            {
                std::cout << "构建进程" << std::endl;
                // threads.push_back(std::make_shared<Thread>(std::bind(&threadpool::defaultfun,this)));
                threads.push_back(std::make_shared<std::thread>(&threadpool::HandlerTask,this,"线程"));
            }
        }
        threadpool(const threadpool<T>& tt) = default;
        threadpool<T>& operator=(const threadpool<T>& tt) = default;
    public:

        void Equeue(T data)
        {
            std::cout << "放入任务" << std::endl;
            if (!_isruning) return;
            std::lock_guard<std::mutex> guard(_mtx);
            _taskq.push(data);
            if (_wait_num > 0) _cond.notify_one();
        }

        void Wait() // 等待进程
        {
            if (_isruning) 
            {
                _cond.notify_all();
            }
            _isruning = false;
            for (auto thread_ptr : threads)
            {
                std::cout << "队列中还剩下： " << _taskq.size() << std::endl;
                thread_ptr->join();
                std::cout << "回收线程: " <<   " 成功";

            }
        }

        ~threadpool()
        {
        }
        //懒汉模式
        static threadpool<T>* _myinstance;
        static std::mutex mutx;
        static threadpool<T>* Getinstance()
        {
            //如果有多个线程初始化单例呢? 加锁保护 
            if (threadpool<T>::_myinstance == nullptr)
            {
                std::lock_guard<std::mutex> lock(mutx);
                if (threadpool<T>::_myinstance == nullptr)
                {
                    std::cout << "我要开始初始化了" << std::endl;
                    threadpool<T>::_myinstance = new threadpool();
                }
            }
            return threadpool<T>::_myinstance;
        }
    private:
        int _num;
        std::vector<thread_t> threads;
        std::queue<T> _taskq; // 任务队列
        std::mutex _mtx;
        std::condition_variable _cond;
        int _wait_num;
        bool _isruning;
    };
    template<class T>
    threadpool<T>* threadpool<T>::_myinstance = nullptr;
    template<class T>
    std::mutex threadpool<T>::mutx;
}